import { IElement } from "./IElement.js";
import { IPainterCharacter } from "./IPainter.js";
import IconFontJson from "./font/iconfont.json";

const glyphs = IconFontJson.glyphs;
const icon_names = new Map();
for (let i = 0; i < glyphs.length; i++) {
    const glyph = glyphs[i];
    icon_names.set(IconFontJson.css_prefix_text + glyph.name, glyph.unicode_decimal);
}

class ICharacter extends IElement {
    constructor() {
        super();
        this.m_character = 0;  // 字符Unicode值
        this.m_painter_character = new IPainterCharacter();
        this.m_character_width = 0;
        this.m_character_height = 0;
        this.SetTagName("ICharacter");
        this.SetFontSize(16);
        this.SetLineHeight(1.5);
        this.SetFontFamily("Arial");
        this.SetFontColor("black");

        this.SetAttributeSetterGetter("value", (value) => { this.SetCharacter(value); });
    }

    SetCharacter(character) {
        if (character instanceof String || typeof character === "string") {
            character = character.codePointAt(0);
        }
        if (!(character instanceof Number) && typeof character !== "number") {
            return;
        }
        if (this.m_character === character) {
            return;
        }
        this.m_character = character;
        this.m_painter_character.SetCharacter(character);
        this.MarkLayoutChanged();
    }

    GetCharacter() { return this.m_character; }
    IsEnglishCharacter() { return this.m_character >= 0 && this.m_character <= 128; }
    IsChineseCharacter() { return this.m_character >= 0x4E00 && this.m_character <= 0x9FFF; }
    IsIconCharacter() { return this.m_character >= 0xE000 && this.m_character <= 0xF8FF; }

    SetFontSize(font_size) {
        if (this.m_font_size === font_size) {
            return;
        }
        this.m_font_size = font_size;
        this.m_painter_character.SetFontSize(font_size);
        this.MarkLayoutChanged();
    }

    SetFontFamily(font_family) {
        if (this.m_font_family === font_family) {
            return;
        }
        this.m_font_family = font_family;
        this.m_painter_character.SetFontFamily(font_family);
        this.MarkLayoutChanged();
    }

    SetLineHeight(line_height) {
        if (this.m_line_height === line_height) {
            return;
        }
        this.m_line_height = line_height;
        this.MarkLayoutChanged();
    }

    GetLayoutWidth() {
        const local_width = this.GetLocalWidth();
        if (local_width > 0) return local_width;
        // 元素样式宽高被设置, 则返回元素样式宽高
        const style_width = this.GetStyleWidth();
        if (style_width >= 0) return style_width;
        // 获取测量宽
        return this.m_character_width + this.GetPaddingBorderWidth();
    }

    GetLayoutHeight() {
        const local_height = this.GetLocalHeight();
        if (local_height > 0) return local_height;
        // 元素样式宽高被设置, 则返回元素样式宽高
        const style_height = this.GetStyleHeight();
        if (style_height >= 0) return style_height;
        // 获取行高
        const line_height = this.GetLineHeight() * this.GetFontSize();
        return (line_height < 0 ? 0 : line_height) + this.GetPaddingBorderHeight();
    }

    UpdateLayout() {
        if (!this.IsLayoutChanged()) {
            this.SetLocalWidth(this.m_cache_local_width);
            this.SetLocalHeight(this.m_cache_local_height);
            return false;
        }

        // 应用样式 重置更新标记和内容宽高
        this.ApplyLayoutStyle();
        this.SetLayoutChanged(false);
        this.SetPositionChanged(true);
        this.SetLocalContentWidth(0);
        this.SetLocalContentHeight(0);

        // 测量字符宽高
        this.GetWindow().GetWindowPainter().RefreshCharacter(this.m_painter_character);
  
        this.m_character_width = this.m_painter_character.GetCharacterWidth();
        this.m_character_height = this.m_painter_character.GetCharacterHeight();

        // 直接设置宽高
        this.SetLocalWidth(this.GetLayoutWidth());
        this.SetLocalHeight(this.GetLayoutHeight());
        this.m_cache_local_width = this.GetLocalWidth();
        this.m_cache_local_height = this.GetLocalHeight();
    }

    OnRenderContent(painter) {
        const x = this.GetContentX() + (this.GetMaxContentWidth() - this.m_character_width) / 2;
        const y = this.GetContentY() + (this.GetMaxContentHeight() - this.m_character_height) / 2;
        painter.FillCharacter(this.m_painter_character, x, y, this.GetFontColor());
    }
}

export function GetIconCharacterByIconName(icon_name) {
    return icon_names.get(icon_name) || 0;
}

class Character extends ICharacter {
    constructor() {
        super();
        this.SetTagName("Character");
    }
}

class Icon extends ICharacter {
    constructor() {
        super();
        this.SetTagName("Icon");
        this.SetFontFamily("iconfont");
        this.SetAttributeSetterGetter("value", (value) => { this.SetValue(value); });
    }

    SetValue(value) {
        this.m_value = value;
        this.SetCharacter(icon_names.get(value) || 0);
    }

    GetValue() {
        return this.m_value;
    }
}

export { ICharacter, Character, Icon };